package com.whity.towerdefense.view;

import java.io.IOException;
import javax.microedition.khronos.opengles.GL10;

import com.whity.towerdefense.Utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;

public class GraphicHeart
{
	// =============================================================
	// Private attributs :
	
	private static final String 		TAG = "com.djm.test03.view";
	
	private final String				m_Directory;
	
	// =============================================================
	// Protected attributs :
	
	private int[] 						m_AnimationTextures;
	protected int						m_ResolutionX;
	protected int 						m_ResolutionY;
	
	// =============================================================
	// Public functions :
	
	public GraphicHeart(String p_Path) throws Exception
	{
		Log.i(TAG, "New GraphicHeart (" + p_Path + ")");
		m_Directory = p_Path;
		m_ResolutionX = -1;
		m_ResolutionY = -1;
		
		// Get the list of all files in the directory :
		try
		{
			String[] anims = GameView.ASSETS_MANAGER.list(m_Directory);
			for(String animFile : anims)
			{
				if(animFile.equals("idle.png"))
				{
					BitmapFactory.Options opts = new BitmapFactory.Options();
					opts.inJustDecodeBounds = true;
					BitmapFactory.decodeStream(GameView.ASSETS_MANAGER.open(m_Directory + "/" + animFile), null, opts);
					m_ResolutionX = opts.outWidth;
					m_ResolutionY = opts.outHeight;
					break;
				}
			}
		}
		catch (IOException e)
		{
			Log.e(TAG, "Can't list the file in this directory : " + m_Directory + "\nError : " + e.toString());
			System.exit(-2);
		}
		
		if(m_ResolutionX <= 0 || m_ResolutionY <= 0)
		{
			Log.e(TAG, "Invalide Graphic heart, miss an 'idle' image, default size set (300, 300)");
			m_ResolutionX = 300;
			m_ResolutionY = 300;
		}
	}
	
	public void LoadGraphism(GL10 p_GL)
	{
		// Get the list of all files in the directory :
		try
		{
			String[] anims = GameView.ASSETS_MANAGER.list(m_Directory);
			m_AnimationTextures = new int[AnimationType.TOTAL_ANIMATIONS];
			for(int i = 0 ; i < AnimationType.TOTAL_ANIMATIONS ; i++)
			{
				m_AnimationTextures[i] = -1;
			}
			
			for(String animFile : anims)
			{
				if(!animFile.endsWith(".png"))
					continue;
				
				Bitmap animImage = BitmapFactory.decodeStream(GameView.ASSETS_MANAGER.open(m_Directory + "/" + animFile));
				int offset = -1;
				
				if(animFile.equals("idle.png"))
				{
					offset = AnimationType.IDLE;
				}
				else
				{
					Log.w(TAG, "Unknow animation skipped : " + animFile + " in directory : " + m_Directory);
					continue;
				}
				
				// Tell OpenGL to generate textures.
				p_GL.glGenTextures(1, m_AnimationTextures, offset);
				
				p_GL.glBindTexture(GL10.GL_TEXTURE_2D, m_AnimationTextures[offset]);
				
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
				
				GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, animImage, 0);
				animImage.recycle();
			}
			
			// If IDLE isn't loaded, we will load the default image
			if(m_AnimationTextures[AnimationType.IDLE] == -1)
			{
				Log.w(TAG, "No idle image define for : " + m_Directory);
				if(GraphicEltFactory.ERROR_IMAGE == null)
				{
					try
					{
						GraphicEltFactory.ERROR_IMAGE = BitmapFactory.decodeStream(GameView.ASSETS_MANAGER.open(Utils.PANIC_IMAGE));
					} catch (IOException e)
					{
						Log.e(TAG, "Can't load the panic display image : " + Utils.PANIC_IMAGE + "\nerror : " + e.toString());
						System.exit(Utils.CANT_LOAD_PANIC_IMAGE);
					}
				}
				
				Bitmap animImage = GraphicEltFactory.ERROR_IMAGE;
				// Tell OpenGL to generate textures.
				p_GL.glGenTextures(1, m_AnimationTextures, AnimationType.IDLE);
				
				p_GL.glBindTexture(GL10.GL_TEXTURE_2D, m_AnimationTextures[AnimationType.IDLE]);
				
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
				p_GL.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
				
				GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, animImage, 0);
			}
		}
		catch (IOException e)
		{
			Log.e(TAG, "Can't list the file in this directory : " + m_Directory + "\nError : " + e.toString());
			System.exit(-2);
		}
	}
	
	public void UnloadGraphism(GL10 p_GL)
	{
		for(int i = 0 ; i < AnimationType.TOTAL_ANIMATIONS ; i++)
		{
			if(m_AnimationTextures[i] != -1)
			{
				p_GL.glDeleteTextures(1, m_AnimationTextures, i);
				m_AnimationTextures[i] = -1;
			}
		}
	}
	
	public int GetTextureID()
	{
		return m_AnimationTextures[0];
	}
	
	// =============================================================
	// Private function
		
	public int createProgram(String p_VertexSource, String p_FragmentSource)
	{
	    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, p_VertexSource);
	    int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, p_FragmentSource);

	    int program = GLES20.glCreateProgram();
	    if (program != 0)
	    {
	        GLES20.glAttachShader(program, vertexShader);
	        checkGlError("glAttachShader");
	        
	        GLES20.glAttachShader(program, pixelShader);
	        checkGlError("glAttachShader");
	        
	        GLES20.glLinkProgram(program);
	        int[] linkStatus = new int[1];
	        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
	        
	        if (linkStatus[0] != GLES20.GL_TRUE)
	        {
	            Log.e(TAG, "Could not link program: ");
	            Log.e(TAG, GLES20.glGetProgramInfoLog(program));
	            GLES20.glDeleteProgram(program);
	            program = 0;
	        }
	    }
	    return program;
	}
	
	private int loadShader(int p_ShaderType, String p_Source)
	{
	    int shader = GLES20.glCreateShader(p_ShaderType);
        if (shader != 0) {
            GLES20.glShaderSource(shader, p_Source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                Log.e(TAG, "Could not compile shader " + p_ShaderType + ":");
                Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
	}
	
	private void checkGlError(String p_Op)
	{
		int error;
		while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)
		{
		    Log.e(TAG, p_Op + ": glError " + error);
		    throw new RuntimeException(p_Op + ": glError " + error);
		}
	}
	
	// =============================================================
}
